package com.lagou.server;

import com.lagou.constant.Constant;
import com.lagou.handler.UserServerHandler;
import com.lagou.rpc.*;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ServerBootstrap implements InitializingBean, ApplicationContextAware {
//    public static void main(String[] args) throws InterruptedException {
//        SpringApplication.run(ServerBootstrap.class, args);
//        UserServiceImpl.startServer("127.0.0.1", 8990);
//    }

    @Value("${rpc.server.hostName}")
    private String hostName;

    @Value("${rpc.server.port}")
    private int port;

    @Autowired
    CuratorFramework curatorFramework;

//    @Autowired
//    UserServerHandler userServerHandler;

    private ApplicationContext applicationContext;

    private static final Logger logger = LoggerFactory.getLogger(ServerBootstrap.class);

    //hostName:ip地址  port:端口号
    public void startServer() throws InterruptedException {
        new Thread(()->{
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                io.netty.bootstrap.ServerBootstrap serverBootstrap = new io.netty.bootstrap.ServerBootstrap();
                serverBootstrap.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            protected void initChannel(SocketChannel ch) throws Exception {
                                ChannelPipeline pipeline = ch.pipeline();
                                pipeline.addLast(new RpcEncoder(RpcResponse.class, new JSONSerializer()));
                                pipeline.addLast(new RpcDecoder(RpcRequest.class, new JSONSerializer()));
                                pipeline.addLast(new UserServerHandler(applicationContext));

                            }
                        });
                ChannelFuture cf =serverBootstrap.bind(hostName, port).sync();
                logger.info("{}:{}服务启动成功",hostName, port);
//                cf.channel().closeFuture().sync();
                //TODO 注册服务到zk
                registerServiceZk(Constant.USER_SERVICE_NAME, hostName, port);
            }catch (InterruptedException e) {
                e.printStackTrace();
                logger.error("{}:{}服务启动失败，原因{}",hostName, port, e.getMessage());
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }).start();
    }

    private void registerServiceZk(String userServiceName, String hostName, int port) {
        try {
            String path = Constant.SERVIE_PATH_ZK + "/" + userServiceName + "/" + Constant.SERVICE_NODE + "/" + userServiceName;
            String data = hostName + ":" + port;
            String ret = curatorFramework.create().creatingParentsIfNeeded().
                    withMode(CreateMode.EPHEMERAL_SEQUENTIAL).
                    forPath(path, data.getBytes());
            UserServerHandler.setServiceNodeName(ret.substring(ret.lastIndexOf("/") + 1));
            logger.info("创建服务{}成功,返回值{}", userServiceName, ret);
        }catch (Exception e){
            logger.error("创建服务{}节点信息失败{}",userServiceName,e);
        }
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        startServer();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
